package apiserver

import (
	"bytes"
	"context"
	"fmt"
	"github.com/patrickmn/go-cache"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	bussrv "gluenet/modules/manager/apiserver/bus-srv"
	"gluenet/modules/manager/apiserver/daemon"
	"gluenet/modules/manager/apiserver/validator"
	"gluenet/modules/manager/apiserver/web-srv"
	"gluenet/pkg/apis"
	"gluenet/pkg/log/v1"
	"time"
)

type Gluenets struct {
	ctx   context.Context
	label string

	logger v1.Logger

	// three kind of server
	Websrv *web_srv.WebServices
	Bussrv *bussrv.BusServices
	Daemon *daemon.Daemon

	// modules server are relate
	report *cache.Cache
}

func (r *Gluenets) InitFlag(flags *pflag.FlagSet) {
}

func (r *Gluenets) ViperConfig(viper *viper.Viper) {
}

func (r *Gluenets) InitViper(viper *viper.Viper) {
}

func (r *Gluenets) Config(opts ...apis.FuncOption) {
	for _, apply := range opts {
		apply(r)
	}
}

func (r *Gluenets) Initialize(logger v1.Logger, ctx *apis.GlueContext) {
	// todo init
	r.logger = logger
	v := validator.NewValidator(ctx.DataBase)
	ctx.Validate = v
	ctx.Report = r.report

	// todo initialize service
	r.Websrv.Initialize(v1.NewLogger(r.label+".service"), ctx)

	// todo initialize bus-srv
	r.Bussrv.Initialize(v1.NewLogger(r.label+".bus-srv"), ctx)

	// todo initialize daemon
	r.Daemon.Initialize(v1.NewLogger(r.label+".daemon"), ctx)

}

func (r *Gluenets) Close() error {
	errs := new(bytes.Buffer)
	if err := r.Websrv.Close(); err != nil {
		errs.WriteString(fmt.Sprintf("%v\n", err))
	}
	if err := r.Bussrv.Close(); err != nil {
		errs.WriteString(fmt.Sprintf("%v\n", err))
	}
	if err := r.Daemon.Close(); err != nil {
		errs.WriteString(fmt.Sprintf("%v\n", err))
	}

	if errs.Len() <= 0 {
		return nil
	} else {
		return fmt.Errorf("%v", errs.String())
	}
}

func NewDefaultServer(ctx context.Context, label apis.Label) apis.GlueRunner {
	return &Gluenets{
		ctx:   ctx,
		label: string(label),

		Websrv: web_srv.NewServices(),
		Bussrv: bussrv.NewServices(ctx),
		Daemon: daemon.NewServices(ctx),
		report: cache.New(time.Second*5, cache.NoExpiration),
	}
}
